package com.example.king.openglenvdemo;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;

import com.example.king.glutils.GlesUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glDrawArrays;
import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glUseProgram;
import static android.opengl.GLES20.glViewport;

/**
 * 画一个三角形-透视投影--修正了宽高比拉伸问题
 */
public class PerspectiveTriangleRenderer implements GLSurfaceView.Renderer {

    private final String mVertexShader =
            "uniform mat4 uModelMatrix;\n" +
            "uniform mat4 uViewMatrix;\n" +
            "uniform mat4 uProjectMatrix;\n" +
            "attribute vec4 aPosition;\n" +
            "void main() {\n" +
            "  gl_Position = uProjectMatrix * uViewMatrix * uModelMatrix * aPosition;\n" +
            "}\n";

    private final String mFragmentShader =
            "void main() {\n" +
            "  gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" +
            "}\n";

    private int mProgram;

    private int maPositionHandle;
    private int mModelMatrixHandle;
    private int mViewMatrixHandle;
    private int mProjectionMatrixHandle;

    private final int FLOAT_SIZE_BYTES = 4;

    private final float[] mPointVerticesData = {
            0.0f, 0.5f, -0.4f,
            -0.5f, -0.5f, -0.4f,
            0.5f, -0.5f, -0.4f
    };

    private FloatBuffer mTriangleVertices;

    private float[] mModelMatrix = new float[16];

    private float[] mViewMatrix = new float[16];

    private final float[] projectionMatrix = new float[16];

    public PerspectiveTriangleRenderer() {
        mTriangleVertices = ByteBuffer.allocateDirect(mPointVerticesData.length * FLOAT_SIZE_BYTES)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer();
        mTriangleVertices.put(mPointVerticesData).position(0);

        Matrix.setRotateM(mModelMatrix, 0, 0, 0, 0, 1.0f);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        mProgram = GlesUtil.linkProgram(mVertexShader, mFragmentShader);
        glUseProgram(mProgram);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        maPositionHandle = glGetAttribLocation(mProgram, "aPosition");
        GlesUtil.catchError("aPosition");

        mModelMatrixHandle = glGetUniformLocation(mProgram, "uModelMatrix");
        GlesUtil.catchError("uModelMatrix");

        mProjectionMatrixHandle = glGetUniformLocation(mProgram, "uProjectMatrix");
        GlesUtil.catchError("uProjectMatrix");

        mViewMatrixHandle = glGetUniformLocation(mProgram, "uViewMatrix");
        GlesUtil.catchError("uViewMatrix");

        mTriangleVertices.position(0);
        GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
                0, mTriangleVertices);

        GLES20.glEnableVertexAttribArray(maPositionHandle);


        GLES20.glUniformMatrix4fv(mModelMatrixHandle, 1, false, mModelMatrix, 0);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        glViewport(0, 0, width, height);

        Matrix.setLookAtM(mViewMatrix, 0, 0f, 0f, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        GLES20.glUniformMatrix4fv(mViewMatrixHandle, 1, false, mViewMatrix, 0);


        float ratio = (float) width / height;
        Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 1, 7);

        // Assign the matrix
        GLES20.glUniformMatrix4fv(mProjectionMatrixHandle, 1, false, projectionMatrix, 0);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
    }
}
